package git.soulbgm.loadbalancer;

import git.soulbgm.config.ProxyConfig;
import git.soulbgm.pojo.Backend;
import git.soulbgm.health.BackendHealthChecker;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 轮询（Round Robin）负载均衡器实现类
 *
 * <p>使用轮询算法在多个后端服务器之间分配负载。每次请求会按顺序选择下一个可用的后端服务器，
 * 从而确保请求被均匀地分布到所有健康的后端服务器。</p>
 *
 * <p>主要功能：</p>
 * <ul>
 *   <li>维护后端服务器列表</li>
 *   <li>使用轮询算法选择后端服务器</li>
 *   <li>跳过不健康的后端服务器</li>
 *   <li>支持动态添加/移除后端服务器</li>
 * </ul>
 *
 * @author soulbgm
 * @version 1.0
 * @since 1.0
 */
public class RoundRobinLoadBalancer {
    /**
     * 当前轮询位置的原子计数器
     */
    private final AtomicInteger currentIndex = new AtomicInteger(0);
    private final BackendHealthChecker healthChecker;

    public RoundRobinLoadBalancer(BackendHealthChecker healthChecker) {
        this.healthChecker = healthChecker;
    }

    /**
     * 获取下一个健康的后端服务器
     * <p>
     * 使用轮询算法选择下一个要使用的后端服务器。该方法是线程安全的，
     * 通过{@link AtomicInteger#getAndUpdate(java.util.function.IntUnaryOperator)}
     * 确保在并发情况下计数器的正确性。
     * </p>
     *
     * @return 选中的后端服务器配置
     * @throws IllegalStateException 如果没有可用的后端服务器
     */
    public Backend getNextBackend() {
        List<Backend> backends = ProxyConfig.getInstance().getBackends();
        if (backends.isEmpty()) {
            throw new IllegalStateException("没有可用的后端服务器");
        }

        // 最多尝试所有后端服务器一次
        int attempts = backends.size();
        while (attempts > 0) {
            int index = currentIndex.getAndUpdate(i -> (i + 1) % backends.size());
            Backend backend = backends.get(index);

            if (healthChecker.isHealthy(backend)) {
                return backend;
            }
            attempts--;
        }

        throw new IllegalStateException("没有健康的后端服务器可用");
    }
} 